

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: fzykd
 * Date: 2022-11-08
 * Time: 23:53
 */

class MyBlockQueue {
    //先实现一个循环队列 在进行阻塞
    public int[] elem = new int[10000];
    //头
    public int first;
    //尾
    public int tail;
    //有效数据个数
    public int size;

    //实现阻塞效果 专门的锁对象
    private Object locker = new Object();

    //入队列
    public void push(int val) throws InterruptedException {
        //判断满不满
        if (size == elem.length){
            //满了就阻塞 等待出队列之后来通知
            synchronized (locker){ //这个锁对象可以包整个代码块 涉及到锁的粒度
                //代码块越小 粒度细 并发度高
                //粒度粗 加锁开销小
                locker.wait();
            }
        }
        elem[tail] = val;
        tail++;
        //处理tail走到最后
        if(tail >= elem.length){
            tail = 0;
        }
        size++;
        synchronized (locker){
            locker.notify();
        }
    }

    //出队列
    public Integer take() throws InterruptedException {
        //判断空不空
        if (size == 0){
            //空了也是要阻塞
            synchronized (locker){
                locker.wait();
                //等待入队列了来通知
            }
        }
        int ret = elem[first];
        first++;
        if (first == elem.length){
            first = 0;
        }
        size--;
        synchronized (locker){
            locker.notify();
        }
        return ret;
    }

}


//实现一个线程安全的阻塞队列 实现一个生产者消费者模型
public class TestDemo {
    private static MyBlockQueue queue = new MyBlockQueue();

    //实现一个生产者消费者模型
    public static void main(String[] args) {

        Thread t = new Thread(()->{
            int num = 0;
            while (true){
                try {
                    System.out.println("生产了: " + num);
                    queue.push(num);
                    num++;
                    //Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();

        Thread t1 = new Thread( () -> {
            while (true){
                try {
                    int num = queue.take();
                    System.out.println("消费了: " + num);
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
    }


    public static void main1(String[] args) throws InterruptedException {
        MyBlockQueue queue = new MyBlockQueue();
        queue.push(10);
        queue.push(20);
        queue.push(30);
        queue.push(40);

    }
}
